package czk.concrent.juc.AQS.practice;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * 自定义锁的实现
 * @Author:ChenZhangKun
 * @Date: 2020/8/1 23:03
 */
public class AqsDemo {
    public static void main(String[] args) throws InterruptedException {
        Aqs aqs=new Aqs();
        new Thread(()->{
            try {
                System.out.println("加锁");
                aqs.lock();
                TimeUnit.SECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                aqs.unlock();
                System.out.println("线程一解锁成功");
            }
        }).start();
        Thread.sleep(1000);
        new Thread(()->{
            try {
                System.out.println("没有锁，阻塞极端");
                aqs.lock();
                System.out.println("啊，我拿到钥匙了");
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                aqs.unlock();
            }
        }).start();
    }
}
// 实现锁接口
class Aqs implements Lock {
    // 内部维护一个aps类
    class MyAqs extends AbstractQueuedSynchronizer{
        // 上锁
        @Override
        protected boolean tryAcquire(int arg) {
            if (compareAndSetState(0,arg)){
                // 成功
                // 设置当前线程
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }
        // 释放锁

        @Override
        protected boolean tryRelease(int arg) {
           try {
               // 线程持有者为null
               setExclusiveOwnerThread(null);
               // 设置状态为0
               setState(arg);
               return true;
           }catch (Exception ex){

           }
           return false;
        }
        // 是否持有独占锁

        @Override
        protected boolean isHeldExclusively() {
            return getState()==1;
        }
        // 休息室
        public Condition newCondition(){
            return new ConditionObject();
        }
    }
    MyAqs myAqs=new MyAqs();
    @Override
    public void lock() {
        myAqs.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        myAqs.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return myAqs.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return myAqs.tryAcquireNanos(1,unit.toNanos(time));
    }

    @Override
    public void unlock() {
        myAqs.release(0);
    }

    @Override
    public Condition newCondition() {
        return myAqs.newCondition();
    }
}
